package ui.frame.dialog;


import static constants.GTextbookConstants.Database;
import static constants.GTextbookConstants.DatabaseName;
import static constants.GTextbookConstants.DatabaseUserName;
import static constants.GTextbookConstants.DatabasePassWord;
import static constants.GTextbookConstants.Query_Text_Area_Dimension;
import static constants.GTextbookConstants.Chinese;
import static constants.GTextbookConstants.English;
import static constants.GTextbookConstants.Input_Chinese_Font;
import static constants.GTextbookConstants.Input_English_Font;
import static constants.GTextbookConstants.authorContext;
import static constants.GTextbookConstants.knowledgeObject;
import static constants.GTextbookConstants.language;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Enumeration;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import prefuse.data.Tree;

import ui.Utility;
import ui.frame.GTextbook;
import ui.frame.QueryFrame;
import ui.frame.dialog.panel.LangButton;
import ui.frame.dialog.panel.TagPanel;
import ui.view.DnDIndexTree;
import ui.view.IndexTree;
import ui.view.IndexTreeNode;
import ui.view.IndexTreeView;
import ui.view.LangWarningPane;
import ui.view.NodeInfo;
import ui.view.QueryIndexTree;
import ui.view.ViewStructure;
import ui.view.prefuseTreeView;



public class QueryPanel extends JPanel implements ActionListener{
	
	public QueryPanel(GTextbook theApp, JFrame view, int whichField, String engTitle, String chiTitle, int language){
		//initial the parent frame
		this.view = view;
		this.theApp = theApp;
		this.language = language;
		this.whichField = whichField;
		//construct the command area
		textArea = new JTextArea();
		if(whichField == constants.GTextbookConstants.Textbook){
			textArea.setText("keyWords[*]");
		}else
			if(whichField == constants.GTextbookConstants.Database){
				textArea.setText("browseBy[Role,Name]");
			}
		
		//put the text area in a scroll pane
		textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);       
		JScrollPane scrollPane = new JScrollPane(textArea);
		scrollPane.setPreferredSize(Query_Text_Area_Dimension);
		
		TagPanel tagPanel = new TagPanel(engTitle, chiTitle, language);
		
		//		set the look of components
        if(language == English){
        	textArea.setFont(Input_English_Font);
        }
        if(language == Chinese){
        	textArea.setFont(Input_Chinese_Font);
        }
        
        //create the button for showing the category 
        show = new LangButton("Show structure", "查看结构", language);
        query = new LangButton("Query", "搜索", language);
        tree = new LangButton("Show Tree", "查看目录", language);
        
        
        show.addActionListener(this);
        query.addActionListener(this);
        tree.addActionListener(this);
        
        //layout the components       
        Box box = Box.createVerticalBox();box.setBorder( BorderFactory.createEmptyBorder(10,10,10,10));
        Box buttonBox = Box.createHorizontalBox();

        buttonBox.add(show);
        buttonBox.add(query);
        box.add(scrollPane);
        box.add(buttonBox);        
        tagPanel.add(box);
  
        splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,true,tagPanel,tree);
        splitPane.setOneTouchExpandable(true);	
        splitPane.setDividerSize(0);
        
        add(splitPane);
        

	}
	
	private JTextArea textArea;
	public JTextArea getTextArea() {
		return textArea;
	}

	public void setTextArea(JTextArea textArea) {
		this.textArea = textArea;
	}

	private JFrame view;
	private JSplitPane splitPane;

	private LangButton show, query, tree;
	private IndexTreeView resultTreeView;
	private GTextbook theApp;
	private int language;
	private int whichField;

	
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		
		final String str = this.getTextArea().getText();
		System.out.println(str);
		

	
			
			if(whichField == constants.GTextbookConstants.Database){
				//set the User_Name to be Administrator
				
				if(e.getSource() == show){
					//tree.setVisible(true);
					//splitPane.setDividerSize(8);
					
					((QueryFrame)getQueryView()).getCarder().show(((QueryFrame)getQueryView()).getCardPane(), "animation");
					((QueryFrame)getQueryView()).getAnimated().start();

					Thread performer = new Thread(new Runnable() {
						public void run() {
							try {
								JFrame frame = ViewStructure.demo("label");
							}finally{

								((QueryFrame)getQueryView()).getAnimated().stop();
								((QueryFrame)getQueryView()).getCarder().show(((QueryFrame)getQueryView()).getCardPane(), "query");
							}
						}
					}, "Performer");
					performer.start();
				}else
				if(e.getSource()==tree){
					((QueryFrame)getQueryView()).getCarder().show(((QueryFrame)getQueryView()).getCardPane(), "animation");
					((QueryFrame)getQueryView()).getAnimated().start();

					Thread performer = new Thread(new Runnable() {
						public void run() {
							try {
								Vector<Tree> trees = prefuseTreeView.initialTree();
								for(int i = 0 ; i < trees.size(); i++){
                    			JComponent treeview = prefuseTreeView.demo(trees.get(i),"label");
	        
                    			JFrame frame = new JFrame(prefuseTreeView.getRoots().get(i));
                    			frame.setContentPane(treeview);
                    			frame.pack();
                    			frame.setVisible(true);
                    		} 
							}finally{

								((QueryFrame)getQueryView()).getAnimated().stop();
								((QueryFrame)getQueryView()).getCarder().show(((QueryFrame)getQueryView()).getCardPane(), "query");
							}
						}
					}, "Performer");
					performer.start();
            
				}else
					if(e.getSource() == query){
			//get the statement of query
			

			
			//perform the query request

			//parse the statement of query

			//query the database and generate the result set

			//generate the xml file of the result

			//render the xml file in the queryFrame

			//parse the result xml file 
			

						((QueryFrame)getQueryView()).getCarder().show(((QueryFrame)getQueryView()).getCardPane(), "animation");
						((QueryFrame)getQueryView()).getAnimated().start();

						Thread performer = new Thread(new Runnable() {
							public void run() {
								try {
    
			                    	/*
			                    	 * the code for query 
			                    	 */
			                    	
			                    	Query query = new Query(str,whichField);
			                    	
			                    	//create the indexTree
			          			  	if(query.root==null){
			          			  		LangWarningPane.showMessageDialog(null,"Sorry, no objects are found!", "抱歉，没有找到您需要的！", "No results", "无结果", JOptionPane.ERROR_MESSAGE, constants.GTextbookConstants.language.getNum());	
			          			  	}else{
			          			  		QueryIndexTree indexTree = new QueryIndexTree(theApp, query.root, Database, query.highlightIDs);
			            				resultTreeView = new IndexTreeView(indexTree);
			          			  		IndexTreeNode treeRoot = indexTree.getTreeRoot();
			          			  		((QueryFrame)getQueryView()).getSplitQueryPane().setRightComponent(resultTreeView);
			          			  	}                   		
                      
								} finally{

									((QueryFrame)getQueryView()).getAnimated().stop();
									((QueryFrame)getQueryView()).getCarder().show(((QueryFrame)getQueryView()).getCardPane(), "query");
								}
							}
						}, "Performer");
						performer.start();
           
					}
		
		}else
			if(whichField == constants.GTextbookConstants.Textbook){
				if(e.getSource() == show){
					JFrame frame = ViewStructure.demo("label");
				}else
					if(e.getSource()==tree){
						Vector<Tree> trees = prefuseTreeView.initialTree();
						for(int i = 0 ; i < trees.size(); i++){
							JComponent treeview = prefuseTreeView.demo(trees.get(i),"label");
							JFrame frame = new JFrame(prefuseTreeView.getRoots().get(i));
							frame.setContentPane(treeview);
							frame.pack();
							frame.setVisible(true);
						}
					}else
						if(e.getSource() == query){	
							
				                  /*
				                   * the code for query 
				                  */
				                    	
					          Query query = new Query(str,whichField);
      			
					           for(int i =0; i <theApp.getView().getIndexTabbedPane().getTabCount(); i++){
					                 ((QueryIndexTree)((IndexTreeView)(theApp.getView().getIndexTabbedPane().getComponentAt(i))).getIndexTree()).setHighlightNodeIDs(query.highlightIDs);
					                  ((IndexTreeView)(theApp.getView().getIndexTabbedPane().getComponentAt(i))).getIndexTree().repaint();
					            }
					        
				                  
						}
			}
		
	}
	
	
	class Query{
		public Query(String input, int whichField){
			//parse the input
			Vector<String> commands = Utility.getItemsBySeparator(input, "&");
			System.out.println(commands.size());
			Vector<IndexTreeNode> viewNodes = new Vector<IndexTreeNode>();
			for(int i = 0 ; i < commands.size(); i++){
				String current = commands.get(i);
				if(current.indexOf("key")!=-1||current.indexOf("Key")!=-1){
					highlightIDs.addAll(queryKeyWords(current));
					System.out.println("node count: " + highlightIDs.size());
				}else
					if(current.indexOf("browse")!=-1||current.indexOf("Browse")!=-1){
						if(whichField == constants.GTextbookConstants.Database){
							viewNodes = browseBy(current);
							System.out.println("category count: " + viewNodes.size());
							if(viewNodes.size()==1){
								root = viewNodes.get(0);
							}else
								if(viewNodes.size()>1){
									root = new IndexTreeNode(new NodeInfo(authorContext.getUserContext(),"Query","Results"));
									for(int j = 0; j < viewNodes.size(); j++){
										root.add(viewNodes.get(j));
									}
								}
						}
					}else
						if(current.indexOf("relation")!=-1||current.indexOf("Relation")!=-1){
							if(whichField == constants.GTextbookConstants.Textbook){
								highlightIDs.addAll(queryRelation(current));
								System.out.println("node count: " + highlightIDs.size());
							}else
								if(whichField == constants.GTextbookConstants.Database){
									Vector<String> result = queryRelation(current); //objectIDs
									for(int j =0; j<result.size(); j++){
						        		  IndexTreeNode child = Utility.getIndexTreeNode(result.get(j));
						        		  if(child!=null){
						        			  viewNodes.add(child);
						        		  }
									}
									if(viewNodes.size()==1){
										root = viewNodes.get(0);
									}else
										if(viewNodes.size()>1){
											root = new IndexTreeNode(new NodeInfo(authorContext.getUserContext(),"Query","Results"));
											for(int j = 0; j < viewNodes.size(); j++){
												root.add(viewNodes.get(j));
											}
										}
								}
						}
			}
			
			
		}
		
		IndexTreeNode root = null;
		Vector<String> highlightIDs= new Vector<String>();
	}

	public static Vector<String> queryRelation(String test){
		Vector<String> nodeIDs = new Vector<String>(1,1);
		Vector<String> terms = Utility.generateTermSetWithSpace(test, '[', ']');
		if(terms.size()==4){
			//list all nodes from the knowledge base
			String preObject = terms.get(1);
			String subObject = terms.get(2);
			String relationType = terms.get(3);
			String get = null;
			String attName = null;
			
			if(preObject.indexOf("*")!=-1 && subObject.indexOf("*")==-1){
				//find precursor
				attName = "precursor"; 
				String nodeID = authorContext.getUserContext() + "." +subObject;
				get = "select distinct precursor from KOstructure where subsequence in (select objectID from allNode where nodeID='"+nodeID+"') " 
				+ (relationType.equals("*")?"":"and "+QueryPanel.queryForLogic(relationType, "relationType"));
			}
			if(subObject.indexOf("*")!=-1 && preObject.indexOf("*")==-1){
					//find subsequence
				attName = "subsequence"; 
				String nodeID = authorContext.getUserContext() + "." +preObject;
				get = "select distinct subsequence from KOstructure where precursor in (select objectID from allNode where nodeID='"+nodeID+"') " 
				+ (relationType.equals("*")?"":"and "+QueryPanel.queryForLogic(relationType, "relationType"));
			}
			System.out.println(get);
			StringBuffer getback = new StringBuffer("select nodeID from allNode where ");
			Connection con = Utility.createConnection(DatabaseName,DatabaseUserName,DatabasePassWord);
			 try{    //这里的异常处理语句是必需的.否则不能通过编译! 

		          Statement st = con.createStatement();
		          ResultSet rs = st.executeQuery(get);
	        	  while(rs.next()){
	        			  getback.append("objectID='" + rs.getString(attName)+"' or ");
	        	  }

	        	  if(getback.lastIndexOf("or")!=-1){
	        		  getback.replace(getback.lastIndexOf("or"), getback.length(), "");
	        	  }
	        	  System.out.println(getback);
	        	  st.close();
	        	  Statement st1 = con.createStatement();
		          ResultSet rs1 = st1.executeQuery(getback.toString());
	        	  while(rs1.next()){
	        			  nodeIDs.add(rs1.getString("nodeID"));

	        	  }
	        	  st1.close();
		          con.close();
		          
			 }catch(Exception err){
		          err.printStackTrace(System.out);
		     }
		}
		 return nodeIDs;
	}
	
	
	public static Vector<String> queryKeyWords(String test){
		Vector<String> nodeIDs = new Vector<String>(1,1);
		Vector<String> terms = Utility.generateTermSetWithSpace(test, '[', ']');
		if(terms.size()==2){
		//list all nodes from the knowledge base
		Connection con = Utility.createConnection(DatabaseName,DatabaseUserName,DatabasePassWord);
		 try{    //这里的异常处理语句是必需的.否则不能通过编译! 

	          Statement st = con.createStatement();
	          String getstr = "select nodeID from allNode where objectID in (select objectID from keyWords where "+queryForLogic(terms.get(1),"keyWord") + ")";
        	 System.out.println(getstr);
	          ResultSet rs = st.executeQuery(getstr);
        	  while(rs.next()){
        			  nodeIDs.add(rs.getString("nodeID"));

        	  }
	          st.close();
	          con.close();
	          
		 }catch(Exception err){
	          err.printStackTrace(System.out);
	     }
		}
		 return nodeIDs;
	}
	
	public static String queryForLogic(String command, String attr){
		StringBuffer result = new StringBuffer(50);
		if(command.indexOf("(")!=-1 || command.indexOf("[")!=-1){
			Vector<String> list = new Vector<String>(1,1);
			if(command.indexOf("[")!=-1){
				 list = Utility.generateTermSetWithSpace(command, '[', ']');
			}else{
				list = Utility.generateTermSetWithSpace(command, '(', ')');
			}
			if(list.get(0).indexOf("or")!=-1||list.get(0).indexOf("OR")!=-1){
				result.append(queryForOr(command,attr));
			}else
				if(list.get(0).indexOf("and")!=-1||list.get(0).indexOf("AND")!=-1){
					result.append(queryForAnd(command,attr));
				}
		
		
		}else{
			if(attr.equals("role")){
				result.append(attr+"='"+Utility.getEnglishRole(command)+"'");
			}else{
				result.append(attr+"='"+Utility.squote2dquote(command)+"'");
			}
		}
		return result.toString();
	}
	
	public static StringBuffer queryForOr(String command, String attr){
		StringBuffer result = new StringBuffer(50);
		if(command.indexOf("(")!=-1 || command.indexOf("[")!=-1){
			Vector<String> list = new Vector<String>(1,1);
			if(command.indexOf("[")!=-1){
				 list = Utility.generateTermSetWithSpace(command, '[', ']');
			}else{
				list = Utility.generateTermSetWithSpace(command, '(', ')');
			}
			result.append("(");
			for(int i = 1; i < list.size()-1; i++){
				result.append(queryForLogic(list.get(i),attr)+" or ");
			}
			result.append(queryForLogic(list.get(list.size()-1),attr)+")");
		}
		return result;
		
	}
	
		
	/**
	 * command := and(A,B,C)
	 * @param command
	 */
	public static StringBuffer queryForAnd(String command, String attr){
		StringBuffer result = new StringBuffer(50);
		if(command.indexOf("(")!=-1 || command.indexOf("[")!=-1){
			Vector<String> list = Utility.generateTermSetWithSpace(command, '[', ']');
			result.append("(");
			for(int i = 1; i < list.size()-1; i++){
				result.append(queryForLogic(list.get(i),attr)+" and ");
			}
			result.append(queryForLogic(list.get(list.size()-1),attr)+")");
		}
		return result;
		
	}
	
	/**
	 * command := [role,name,userName] 
	 * @param command
	 * @return
	 */
	public static Vector<IndexTreeNode> browseBy(String command){
		Vector<IndexTreeNode> nodes = new Vector<IndexTreeNode>(1,1);
		Vector<String> list = Utility.generateTermSetWithSpace(command, '[', ']');
		String rootObjectID = null;
		if(list.size()==1||(list.size()==2&&(Utility.deleteSpace(list.get(1)).equals("*")))){
			
			//list all nodes from the knowledge base
			Connection con = Utility.createConnection(DatabaseName,DatabaseUserName,DatabasePassWord);
			 try{    //这里的异常处理语句是必需的.否则不能通过编译! 

		          Statement st = con.createStatement();
		          String getAllNodes = "select distinct nodeID from allNode";
	        	  ResultSet children = st.executeQuery(getAllNodes);
	        	  while(children.next()){
	        		  IndexTreeNode child = Utility.getIndexTreeNode(children.getString("nodeID"));
	        		  if(child!=null){
	        			  nodes.add(child);
	        		  }
	        	  }
	        	  
		          st.close();
		          con.close();
		          
			 }catch(Exception err){
		          err.printStackTrace(System.out);
		     }
			
		}else
			if(list.size()==2){
				if(!Utility.deleteSpace(list.get(1)).equals("")){
					//objectID 存在
					rootObjectID = list.get(1);
				}
				
			}else
				if(list.size()==3||list.size()==4){
					String role = list.get(1);
					String name = list.get(2);
					System.out.println(role);
					System.out.println(name);
					String userName = null;
					if(list.size()==3){
						userName = authorContext.getUserContext();
					}else{
						userName = list.get(3);
					}
				
					
					
					//if(Utility.deleteSpace(role).equals("*")){
						Vector<String> knowledgeIDs = Utility.getKnowledgeID(userName, role, name);
						for(int i = 0; i < knowledgeIDs.size(); i++){
							System.out.println(knowledgeIDs.get(i));
							if(knowledgeIDs.get(i)!=null){
								IndexTreeNode node = Utility.getIndexTreeNode(knowledgeIDs.get(i));
								if(node!=null){
									nodes.add(node);
								}
							}

						}
						Vector<String> categoryIDs = Utility.getCategoryID(userName, role, name);
						for(int i = 0; i < categoryIDs.size(); i++){
							nodes.add(IndexTree.generateTreeFromKB(categoryIDs.get(i)));
						}
				/*	}else{
						if(Utility.checkOntology("roleOntology", Utility.getEnglishRole(role) , "precursor", "knowledgeObject", "subsequence", "is")){
							Vector<String> knowledgeIDs = Utility.getKnowledgeID(userName, Utility.getEnglishRole(role), name);
							for(int i = 0; i < knowledgeIDs.size(); i++){
								IndexTreeNode node = IndexTree.getIndexTreeNode(knowledgeIDs.get(i));
								if(node!=null){
									nodes.add(node);
								}
							}
							
							//System.out.println(Utility.getKnowledgeID(userName, name, role));
						}else{
							Vector<String> categoryIDs = Utility.getCategoryID(userName, role, name);
							for(int i = 0; i < categoryIDs.size(); i++){
								nodes.add(IndexTree.generateTreeFromKB(categoryIDs.get(i)));
							}
						}
					}*/
					
				}
		

		return nodes;
	}
	
	

	public JFrame getQueryView() {
		return view;
	}

	public void setView(QueryFrame view) {
		this.view = view;
	}
}
